import mysqlPool
import publicfun
import os
import subprocess
import cfg
import logging_config
from obs import ObsClient
import urllib
import urllib.request
import datetime
import json

logger = logging_config.Config().get_config()
BASE_PATH=publicfun.get_current_path()+"/tmp/"

obsClient = ObsClient(
    access_key_id = cfg.AccessKey,       
    secret_access_key=cfg.SecretKey,    
    server=cfg.obsServer
)

class task():

    #增加一条新记录
    def addTask(self, _id, ossUrl, objectKey, callbackUrl):
        sql = "insert into task (_id, ossUrl, objectKey, callbackUrl) values(%s, %s, %s, %s)"
        param = (_id, ossUrl, objectKey, callbackUrl)
        conn = mysqlPool.global_pool.connection()
        cursor = conn.cursor()
        cursor.execute(sql, param)
        return

    #解锁所有本进程锁定的记录
    def unlockTask(self, server_fg):

        sql = "update task set rlock = 0, owner='' where rlock = 1 and owner='"+server_fg+"'"
        logger.debug(sql)
        cursor = mysqlPool.global_pool.connection().cursor()
        results = cursor.execute(sql)

    #锁定一条未处理的记录
    def lockTask(self, server_fg):

        sql = "update task set rlock = 1, try=try+1, owner ='"+server_fg+"', ltime=now() where try<="+str(cfg.re_denoise)+" and rlock = 0 order by ctime desc limit 1"
        cursor = mysqlPool.global_pool.connection().cursor()
        results = cursor.execute(sql)
        return

    #获取锁定的记录
    def getLockTask(self, server_fg):

        res = {}
        sql = "select taskid, _id, ossUrl, objectKey, callbackUrl from task where rlock = 1 and owner ='"+server_fg+"' limit 1"
        logger.debug(sql)
        cursor = mysqlPool.global_pool.connection().cursor()
        cursor.execute(sql)
        row = cursor.fetchone()
        if row:
            res["taskid"] = row[0]
            res["_id"] = row[1]
            res["ossUrl"] = row[2]
            res["objectKey"] = row[3]
            res["callbackUrl"] = row[4]
        return res

    #锁定一条超出尝试次数未处理成功的记录
    def lockFaultTask(self, server_fg):

        sql = "update task set rlock = 1, status = -1, step = 1, owner ='"+server_fg+"', ltime=now() where rlock = 0 and try > "+str(cfg.re_denoise)+" order by ctime desc limit 1"
        logger.debug(sql)
        cursor = mysqlPool.global_pool.connection().cursor()
        results = cursor.execute(sql)
        return

    #把失败的任务从task表中移到
    def mvFaultTask(self, server_fg):

        sql = "insert into task_cb(taskid, _id, ossUrl, objectKey, callbackUrl, status, step, info) select taskid, _id, ossUrl, objectKey, callbackUrl, status, step, info from task where status = -1 and rlock = 1 and try > "+str(cfg.re_denoise)+" and owner ='"+server_fg+"'"
        logger.debug(sql)
        cursor = mysqlPool.global_pool.connection().cursor()
        results = cursor.execute(sql)
        sql1 = "delete from task where status = -1 and step = 1 and rlock = 1 and try > "+str(cfg.re_denoise)+" and owner ='"+server_fg+"'"
        logger.debug(sql1)
        cursor = mysqlPool.global_pool.connection().cursor()
        results = cursor.execute(sql1)
        return

    #锁定一条超出尝试次数未处理成功的记录
    def lockFaultCbTask(self, server_fg):

        sql = "update task_cb set rlock = 1, owner ='"+server_fg+"', ltime=now() where rlock = 0 and try > "+str(cfg.re_callback)+" order by ctime desc limit 1"
        cursor = mysqlPool.global_pool.connection().cursor()
        results = cursor.execute(sql)
        return

    #把失败的任务从task表中移到
    def mvFaultCbTask(self, server_fg):

        sql = "insert into task_cb_err select * from task_cb where rlock = 1 and try > "+str(cfg.re_callback)+" and owner ='"+server_fg+"'"
        logger.debug(sql)
        cursor = mysqlPool.global_pool.connection().cursor()
        results = cursor.execute(sql)
        sql1 = "delete from task_cb where rlock = 1 and try > "+str(cfg.re_callback)+" and owner ='"+server_fg+"'"
        logger.debug(sql1)
        cursor = mysqlPool.global_pool.connection().cursor()
        results = cursor.execute(sql1)
        return

    #进行降噪后进行上传和回调
    @staticmethod
    def upload_HW_OBS(sfile, objectKey):

        from obs import PutObjectHeader 

        headers = PutObjectHeader() 
        headers.contentType = 'audio/wav' 

        logger.info("上传华为云开始:"+str(sfile)+" 待上传路径为: "+ cfg.obsServer + "/" + objectKey)
        resp = obsClient.putFile(cfg.bucketName, objectKey, sfile, metadata={}, headers=headers) 

        status = True        
        if resp.status < 300:
            status =  True
        else:
            logger.error("上传华为云错误:"+str(sfile)+" "+str(objectKey))
            status = False
        #删除上传文件内容
        if os.path.exists(sfile):  # 如果文件存在
            logger.info("删除上传成功之后的文件" + str(sfile))
            os.remove(sfile)
        return status

    #系统调用运行转码和降噪
    def shExecutor (self, rjson):

        ossUrl = rjson["ossUrl"]
        objectKey = rjson["objectKey"]
        filename = os.path.basename(ossUrl)
        tf = BASE_PATH+filename+".wav"
        otf = tf+".t.m4a"
        # shcmd = "/usr/bin/ffmpeg -i "+ossUrl+" -ac 1 -ar 8000 -y "+tf+"&&/usr/bin/sox -v 0.5 "+tf+" "+otf+"&&rm -rf "+tf+"&&echo 'OKKKKK!'"
        # shcmd = "/usr/bin/ffmpeg -i "+ossUrl+" -ac 1 -ar 8000 -y "+tf+"&&cd /root/NS_demo/NS_Linux_License/NS_Linux_License&& ./TestVQEPC "+tf+" "+tf+".d.wav 0 1 0&&echo 'OKKKKK!'"
        # shcmd = "/usr/bin/ffmpeg -i "+ossUrl+" -ac 1 -ar 8000 -y "+tf+"&&cd /root/NS_demo/NS_Linux_License/NS_Linux_License&& ./TestVQEPC "+tf+" "+tf+".d.wav 0 1 0 " + "&& ffmpeg -y -i "+tf+".d.wav -ac 1 -ar 8000 -b:a 24k "+tf+".t.m4a  >/dev/null 2>/dev/null && echo 'OKKKKK!'"
        shcmd = "/usr/bin/ffmpeg -i "+ossUrl+" -ac 1 -ar 8000 -y "+tf+"&&cd /root/NS_demo/NS_Linux_License/NS_Linux_License&& ./TestVQEPC "+tf+" "+tf+".d.wav 0 1 0 " + "&& ffmpeg -y -i "+tf+".d.wav -ac 1 -ar 8000 -b:a 24k "+tf+".t.m4a  >/dev/null 2>/dev/null && rm -f "+tf+".d.wav "+tf+" && echo 'OKKKKK!'"
        logger.info(shcmd)
        pipe = subprocess.Popen(shcmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = pipe.communicate()

        #if b'OKKKKK!\n' == stdout:
        if stdout.endswith(b'OKKKKK!\n'):
            if self.upload_HW_OBS(otf, objectKey):
                return True, "上传成功"
            else:
                logger.info(otf + " upload_HW_OBS 上传失败: " + objectKey)
                return False, "上传失败"
        else:
            logger.error("运行shell命令调用错误 rjson:"+str(rjson))
            logger.error("运行shell命令调用错误 stderr:"+ str(stderr))
            logger.error("运行shell命令调用错误 stdout:"+ str(stdout))
            return False, "转换错误"

    #把执行完的内容，迁移到回调记录中，其中有成功处理完的 status= 0，也有处理失败的 status = -1
    def addCallbackTask(self, taskid, status):
        sql = "insert into task_cb(taskid, ctime, _id, ossUrl, objectKey, callbackUrl, step, status, info) select taskid, ctime, _id, ossUrl, objectKey, callbackUrl, 1, "+str(status)+", info from task where taskid="+taskid
        logger.debug(sql)
        conn = mysqlPool.global_pool.connection()
        cursor = conn.cursor()
        cursor.execute(sql)
        return

    #业务处理错误的信息保存到info字段中
    def updateTaskInfo(self, taskid, info):
        sql = "update task set info = '"+info+"' where taskid="+taskid
        logger.info(sql)
        conn = mysqlPool.global_pool.connection()
        cursor = conn.cursor()
        cursor.execute(sql)
        return

    #把执行完成的内容,从task中删除掉
    def delTask(self, taskid):
        sql = "delete from task where taskid="+taskid
        logger.debug(sql)
        conn = mysqlPool.global_pool.connection()
        cursor = conn.cursor()
        cursor.execute(sql)
        return

    #解锁所有本进程锁定的回调的任务记录
    def unlockCbTask(self, server_fg):

        sql = "update task_cb set rlock = 0, owner='' where rlock = 1 and owner='"+server_fg+"'"
        logger.debug(sql)
        cursor = mysqlPool.global_pool.connection().cursor()
        results = cursor.execute(sql)

    #锁定一条未处理的记录
    def lockCbTask(self, server_fg):

        res = {}
        sql = "update task_cb set rlock = 1, try=try+1, owner ='"+server_fg+"', ltime=now() where try<="+str(cfg.re_callback)+"  and rlock = 0 and owner ='' order by ctime desc limit 1"
        cursor = mysqlPool.global_pool.connection().cursor()
        results = cursor.execute(sql)
        return

    #获取锁定的记录
    def getCbLockTask(self, server_fg):

        res = {}
        sql = "select taskid, _id, ossUrl, objectKey, callbackUrl, status, info from task_cb where rlock = 1 and owner ='"+server_fg+"' limit 1"
        logger.debug(sql)
        cursor = mysqlPool.global_pool.connection().cursor()
        cursor.execute(sql)
        row = cursor.fetchone()
        if row:
            res["code"] = row[5]
            res["taskid"] = row[0]
            res["_id"] = row[1]
            res["ossUrl"] = row[2]
            res["objectKey"] = row[3]
            res["callbackUrl"] = row[4]
            if row[5] == -1:
                res["info"] = row[6]
        return res

    #执行回调的任务记录
    def callback(self, rjson):
        #华为云需要动态的组合访问的地址
        obs_server=cfg.obsServer
        bucket = cfg.bucketName
        wav_obs = obs_server.replace("http://", "http://"+bucket+".").replace("https://", "https://"+bucket+".")+"/"+rjson["objectKey"]
        rjson["objectKey"] = wav_obs
        rjson["time"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        nurl = rjson["callbackUrl"]
        
        headers = {'Accept-Charset':'utf-8','Content-Type':'application/json'}
        #data = bytes(urllib.parse.urlencode(rjson), encoding='utf8')
        data =json.dumps(rjson,ensure_ascii=False)
        taskid = str(rjson["taskid"])
        logger.info("任务回调处理, taskid:" + taskid + ", url:" + nurl + " objectKey: " + wav_obs + ", 回调参数 data:" + data)
        try:
            dataBytes = bytes(data, encoding='utf8')
            req = urllib.request.Request(url=nurl, data=dataBytes, headers=headers, method='POST')
            response = urllib.request.urlopen(req, timeout=3)
            if response.status < 300:
                return True
            return False

        except Exception as e:
            logger.error("callback url:"+ nurl + ", 异常信息: " + str(e))
            return False

    #把执行完成的内容，迁移到历史记录中
    def addHistoryTask(self, taskid):
        sql = "insert into task_log(taskid, ctime, _id, ossUrl, objectKey, callbackUrl, step, status, info) select taskid, ctime, _id, ossUrl, objectKey, callbackUrl, 1, status, info from task_cb where taskid="+taskid
        logger.debug(sql)
        conn = mysqlPool.global_pool.connection()
        cursor = conn.cursor()
        cursor.execute(sql)
        return

    #把执行完成的内容,从task中删除掉
    def delCbTask(self, taskid):
        sql = "delete from task_cb where taskid="+taskid
        logger.debug(sql)
        conn = mysqlPool.global_pool.connection()
        cursor = conn.cursor()
        cursor.execute(sql)
        return

    #查询任务的状态
    def queryTask(self, taskid):

        res = {}
        sql = "select 0, try, status, info, ltime, ctime from task where taskid="+taskid +" union " \
              +"select 1, try, status, info, ltime, ctime from task_cb where taskid="+taskid +" union " \
              +"select 2, try, status, info, ltime, ctime from task_cb_err where taskid="+taskid

        logger.debug(sql)
        cursor = mysqlPool.global_pool.connection().cursor()
        cursor.execute(sql)
        row = cursor.fetchone()
        if row:
            res["code"] = 1
            res["taskid"] = taskid
            res["step"] = row[0]
            res["try"] = row[1]
            res["status"] = row[2]
            res["info"] = row[3]
            res["ltime"] = row[4]
            res["ctime"] = row[5]
        return res

if __name__ == '__main__':
    tt = task("1", "2", "3", "4", "5")
    tt.addTask()
